TechNote - COM Surrogate

Friday, February 24, 2023

1:35 PM

OneNote addins run in separate COM surrogate process to isolate any bad behavior from the main ONENOTE.EXE process. These will appear as instances of the dllhost.exe process in Task Manager. In fact, when OneMore does misbehave and you see empty OneMore menus, this is when OneNote has cut off communication because it no longer trusts the add-in for some reason.

 

This design is important. OneMore runs from within the COM surrogate dllhost.exe process, separate from OneNote's main ONENOTE.EXE process. OneNote still controls the entire ribbon and the OneMore ribbon controls, but OneMore renders all of its own dialogs out of the COM surrogate.

 

📓

Task Manager

Open Windows Task Manager, open the Details view, right-click on a column heading, and choose Select columns. Scroll down and tick the Command line column. This will add a column to the Details view showing the full command line used to invoke each process. This makes it easy to identify the dllhost.exe process that hosts the OneMore add-in. The OneMore host will have this command line:

 

C:\WINDOWS\system32\DllHost.exe /Processid:{88AB88AB-CDFB-4C68-9C3A-F10B75A5BC61}

 

The GUID is the same one used to register OneMore as a COM add-in.

 

OneNote isn't explicitly aware or in control of its add-ins and the COM surrogates. Instead, add-ins use the IApplication COM interface to communicate with and send requetss to OneNote. The COM surrogate, by definition, runs in an MTA context.

 

This presents some challenges.

 

  1. OneMore may need to invoke .NET components that are designed to only run in an STA context such as OpenFileDialog or accessing the clipboard. If an add-in attempts to use this class directly, it will cause both the COM surrogate and OneNote to hang.

 

OneMore implements the SingleThreaded helper class, which has a couple of Invoke overloads that accept an Action or Func to execute in an STA thread.

 

This is demonstrated by the ImportDialog class which lets the user browse for a file to import.

 

  1. OneMore may need to present a dialog to the user which interactively modifies the OneNote view or page content while keeping that dialog open. By default, you won't see changes until the dialog is closed.

 

OneMore implements the LocalizableForm.RunModeless method, to avoid blocking the OneNote main UI thread and to invoke given callbacks.

 

This is demonstrated by SearchCommand to present a dialog that lets the user navigate page-to-page looking for the right one to copy or move.

 

  1. OneMore may need to perform lengthy work while presenting a dialog that shows incremental progress while interacting with OneNote. Attempting to do this with a modal dialog will cause the COM surrogate and OneNote to hang.

 

OneMore implements the ProgressDialog class which provides various views of a progress dialog with options to cancel and increment explicitly or across a specified time limit, and run actions and callbacks in a background thread. ProgressDialog also derives from LocalizableForm and, as such, also inherits RunModeless.

 

Its simplest form is demonstrated by DateStampCommand

ShowDialogWithCancel is demonstrated by RemoveDuplicatesCommand

RunModeless is demonstrated by ArchiveCommand

 

Finally, in order to make this all work smoothly and keep the user experience responsive and performant, OneMore relies heavily on async/await. All commands are run asynchronously and, sometimes, additional complexity is added to ensure that all code paths are "async all the way down."

 

#omwiki #omdeveloper #omtechnote

 

© 2020 Steven M Cohn. All rights reserved.

Please consider a sponsorship or one-time donation to support ongoing development

 

 

Created with OneNote.